home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / ANSI / c-client / mtest.c < prev    next >
C/C++ Source or Header  |  1995-09-05  |  17KB  |  641 lines

  1. /*
  2.  * Program:    Mail library test program
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    8 July 1988
  13.  * Last Edited:    5 September 1995
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University
  22.  * Copyright 1995 by the University of Washington
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include <signal.h>
  47. #include "mail.h"
  48. #include "osdep.h"
  49. #include "rfc822.h"
  50. #include "smtp.h"
  51. #include "nntp.h"
  52. #include "misc.h"
  53.  
  54. /* Excellent reasons to hate ifdefs, and why my real code never uses them */
  55.  
  56. #ifdef __MINT__
  57. # define UNIXLIKE 1
  58. # define MAC 1
  59. # define MACOS 0
  60. #else
  61. # if unix
  62. #  define UNIXLIKE 1
  63. #  define MACOS 0
  64. # else
  65. #  define USWPWD 0
  66. #  ifdef noErr
  67. #   define MAC 1
  68. #   define MACOS 1
  69. #  else
  70. #   define MAC 0
  71. #   define MACOS 0
  72. #  endif
  73. # endif
  74. #endif
  75. #if UNIXLIKE
  76. #include <pwd.h>
  77. #endif
  78. #if MAC
  79. #include <MacTCPCommonTypes.h>
  80. #include <AddressXlation.h>
  81. #endif
  82.  
  83. char *curhst = NIL;        /* currently connected host */
  84. char *curusr = NIL;        /* current login user */
  85. char personalname[MAILTMPLEN];    /* user's personal name */
  86. char userbuf[MAILTMPLEN];    /* /user= buffer */
  87.  
  88. static char *hostlist[] = {    /* SMTP server host list */
  89.   "mailhost",
  90.   "localhost",
  91.   NIL
  92. };
  93.  
  94. static char *newslist[] = {    /* Netnews server host list */
  95.   "news",
  96.   NIL
  97. };
  98.  
  99. int main ();
  100. void mm (MAILSTREAM *stream,long debug);
  101. void header (MAILSTREAM *stream,long msgno);
  102. void display_body (BODY *body,char *pfx,long i);
  103. void status (MAILSTREAM *stream);
  104. void prompt (char *msg,char *txt);
  105. void smtptest (long debug);
  106.  
  107. /* Main program - initialization */
  108.  
  109. int main ()
  110. {
  111.   MAILSTREAM *stream = NIL;
  112.   char tmp[MAILTMPLEN];
  113.   long debug;
  114. #include "linkage.c"
  115. #if MACOS
  116.   {
  117.     size_t *base = (size_t *) 0x000908;
  118.                 /* increase stack size on a Mac */
  119.     SetApplLimit ((Ptr) (*base - (size_t) 65535L));
  120.   }
  121. #endif
  122. #if UNIXLIKE
  123. #ifdef __MINT__
  124.     mint_setup ();
  125. #endif
  126.   curusr = cpystr(myusername());/* current user is this name */
  127.   {
  128.     char *suffix;
  129.     struct passwd *pwd = getpwnam (curusr);
  130.     if (pwd) {
  131.       strcpy (tmp,pwd->pw_gecos);
  132.                 /* dyke out the office and phone poop */
  133.       if (suffix = strchr (tmp,',')) suffix[0] = '\0';
  134.       strcpy (personalname,tmp);/* make a permanent copy of it */
  135.     }
  136.     else personalname[0] = '\0';
  137.   }
  138. #else
  139.   curusr = cpystr ("somebody");
  140.   personalname[0] = '\0';
  141. #endif
  142.   curhst = cpystr (mylocalhost ());
  143.   mail_parameters (NIL,SET_USERNAMEBUF,(void *) userbuf);
  144.   puts ("MTest -- C client test program");
  145.   if (!*personalname) prompt ("Personal name: ",personalname);
  146.                 /* user wants protocol telemetry? */
  147.   prompt ("Debug protocol (y/n)?",tmp);
  148.   ucase (tmp);
  149.   debug = (tmp[0] == 'Y') ? T : NIL;
  150.   do {
  151.     prompt ("Mailbox ('?' for help): ",tmp);
  152.     if (!strcmp (tmp,"?")) {
  153.       puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
  154.       puts ("Known local mailboxes:");
  155.       mail_find (NIL,"*");
  156.       puts ("or just hit return to quit");
  157.     }
  158.     else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
  159.   } while (!stream && tmp[0]);
  160.   mm (stream,debug);        /* run user interface if opened */
  161. #ifdef __MINT__
  162.   mint_cleanup ();
  163. #else
  164. # if MACOS
  165.                 /* clean up resolver */
  166.   if (resolveropen) CloseResolver ();
  167. # endif
  168. #endif
  169. }
  170.  
  171. /* MM command loop
  172.  * Accepts: MAIL stream
  173.  */
  174.  
  175. void mm (MAILSTREAM *stream,long debug)
  176. {
  177.   char cmd[MAILTMPLEN],cmdx[MAILTMPLEN];
  178.   char *arg;
  179.   long i;
  180.   long last = 0;
  181.   BODY *body;
  182.   status (stream);        /* first report message status */
  183.   while (stream) {
  184.     prompt ("MTest>",cmd);    /* prompt user, get command */
  185.                 /* get argument */
  186.     if (arg = strchr (cmd,' ')) *arg++ = '\0';
  187.     switch (*ucase (cmd)) {    /* dispatch based on command */
  188.     case 'B':            /* Body command */
  189.       if (arg) last = atoi (arg);
  190.       else if (last == 0 ) {
  191.     puts ("?Missing message number");
  192.     break;
  193.       }
  194.       if (last > 0 && last <= stream->nmsgs) {
  195.     mail_fetchstructure (stream,last,&body);
  196.     if (body) display_body (body,NIL,(long) 0);
  197.     else puts ("%No body information available");
  198.       }
  199.       else puts ("?Bad message number");
  200.       break;
  201.     case 'C':            /* Check command */
  202.       mail_check (stream);
  203.       status (stream);
  204.       break;
  205.     case 'D':            /* Delete command */
  206.       if (arg) last = atoi (arg);
  207.       else {
  208.     if (last == 0) {
  209.       puts ("?Missing message number");
  210.       break;
  211.     }
  212.     arg = cmd;
  213.     sprintf (arg,"%ld",last);
  214.       }
  215.       if (last > 0 && last <= stream->nmsgs)
  216.     mail_setflag (stream,arg,"\\DELETED");
  217.       else puts ("?Bad message number");
  218.       break;
  219.     case 'E':            /* Expunge command */
  220.       mail_expunge (stream);
  221.       last = 0;
  222.       break;
  223.     case 'F':            /* Find command */
  224.       if (!arg) arg = "*";
  225.       puts ("Subscribed mailboxes:");
  226.       mail_find (NIL,arg);
  227.       puts ("Subscribed bboards:");
  228.       mail_find_bboards (NIL,arg);
  229.       puts ("Known mailboxes:");
  230.       mail_find_all (NIL,arg);
  231.       puts ("Known bboards:");
  232.       mail_find_all_bboard (NIL,arg);
  233.       if ((*stream->mailbox == '{') ||
  234.       ((*stream->mailbox == '*') && (stream->mailbox[1] == '{'))) {
  235.     puts ("Remote Subscribed mailboxes:");
  236.     mail_find (stream,arg);
  237.     puts ("Remote Subscribed bboards:");
  238.     mail_find_bboards (stream,arg);
  239.     puts ("Remote known mailboxes:");
  240.     mail_find_all (stream,arg);
  241.     puts ("Remote known bboards:");
  242.     mail_find_all_bboard (stream,arg);
  243.       }
  244.       break;
  245.     case 'G':
  246.       mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
  247.       break;
  248.     case 'H':            /* Headers command */
  249.       if (arg) {
  250.     if (!(last = atoi (arg))) {
  251.       mail_search (stream,arg);
  252.       for (i = 1; i <= stream->nmsgs; ++i)
  253.         if (mail_elt (stream,i)->searched) header (stream,i);
  254.       break;
  255.     }
  256.       }
  257.       else if (last == 0) {
  258.     puts ("?Missing message number");
  259.     break;
  260.       }
  261.       if (last > 0 && last <= stream->nmsgs) header (stream,last);
  262.       else puts ("?Bad message number");
  263.       break;
  264.     case 'M':
  265.       prompt ("Destination: ",cmdx);
  266.       mail_move (stream,arg,cmdx);
  267.       break;
  268.     case 'N':            /* New mailbox command */
  269.       if (!arg) {
  270.     puts ("?Missing mailbox");
  271.     break;
  272.       }
  273.                 /* get the new mailbox */
  274.       while (!(stream = mail_open (stream,arg,debug)))
  275.     prompt ("Mailbox: ",arg);
  276.       last = 0;
  277.       status (stream);
  278.       break;
  279.     case 'Q':            /* Quit command */
  280.       mail_close (stream);
  281.       stream = NIL;
  282.       break;
  283.     case 'S':            /* Send command */
  284.       smtptest (debug);
  285.       break;
  286.     case 'T':            /* Type command */
  287.       if (arg) last = atoi (arg);
  288.       else if (last == 0 ) {
  289.     puts ("?Missing message number");
  290.     break;
  291.       }
  292.       if (last > 0 && last <= stream->nmsgs) {
  293.     printf ("%s",mail_fetchheader (stream,last));
  294.     puts (mail_fetchtext (stream,last));
  295.       }
  296.       else puts ("?Bad message number");
  297.       break;
  298.     case 'U':            /* Undelete command */
  299.       if (arg) last = atoi (arg);
  300.       else {
  301.     if (last == 0 ) {
  302.       puts ("?Missing message number");
  303.       break;
  304.     }
  305.     arg = cmd;
  306.     sprintf (arg,"%ld",last);
  307.       }
  308.       if (last > 0 && last <= stream->nmsgs)
  309.     mail_clearflag (stream,arg,"\\DELETED");
  310.       else puts ("?Bad message number");
  311.       break;
  312.     case 'X':            /* Xit command */
  313.       mail_expunge (stream);
  314.       mail_close (stream);
  315.       stream = NIL;
  316.       break;
  317.     case '+':
  318.       mail_debug (stream); debug = T;
  319.       break;
  320.     case '-':
  321.       mail_nodebug (stream); debug = NIL;
  322.       break;
  323.     case '?':            /* ? command */
  324.       puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Move,");
  325.       puts (" New Mailbox, Quit, Send, Type, Undelete, Xit,");
  326.       puts (" +, -, or <RETURN> for next message");
  327.       break;
  328.     case '\0':        /* null command (type next message) */
  329.       if (last > 0 && last++ < stream->nmsgs) {
  330.     printf ("%s",mail_fetchheader (stream,last));
  331.     puts (mail_fetchtext (stream,last));
  332.       }
  333.       else puts ("%No next message");
  334.       break;
  335.     default:            /* bogus command */
  336.       printf ("?Unrecognized command: %s\n",cmd);
  337.       break;
  338.     }
  339.   }
  340. }
  341.  
  342. /* MM display header
  343.  * Accepts: IMAP2 stream
  344.  *        message number
  345.  */
  346.  
  347. void header (MAILSTREAM *stream,long msgno)
  348. {
  349.   unsigned long i;
  350.   char tmp[MAILTMPLEN];
  351.   char *t;
  352.   MESSAGECACHE *cache = mail_elt (stream,msgno);
  353.   mail_fetchstructure (stream,msgno,NIL);
  354.   tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
  355.   tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
  356.   tmp[2] = cache->flagged ? 'F' : ' ';
  357.   tmp[3] = cache->answered ? 'A' : ' ';
  358.   tmp[4] = cache->deleted ? 'D' : ' ';
  359.   sprintf (tmp+5,"%4ld) ",cache->msgno);
  360.   mail_date (tmp+11,cache);
  361.   tmp[17] = ' ';
  362.   tmp[18] = '\0';
  363.   mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
  364.   strcat (tmp," ");
  365.   if (i = cache->user_flags) {
  366.     strcat (tmp,"{");
  367.     while (i) {
  368.       strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
  369.       if (i) strcat (tmp," ");
  370.     }
  371.     strcat (tmp,"} ");
  372.   }
  373.   mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
  374.   sprintf (t += strlen (t)," (%ld chars)",cache->rfc822_size);
  375.   puts (tmp);
  376. }
  377.  
  378. /* MM display body
  379.  * Accepts: BODY structure pointer
  380.  *        prefix string
  381.  *        index
  382.  */
  383.  
  384. void display_body (BODY *body,char *pfx,long i)
  385. {
  386.   char tmp[MAILTMPLEN];
  387.   char *s = tmp;
  388.   PARAMETER *par;
  389.   PART *part;            /* multipart doesn't have a row to itself */
  390.   if (body->type == TYPEMULTIPART) {
  391.                 /* if not first time, extend prefix */
  392.     if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
  393.     else tmp[0] = '\0';
  394.     for (i = 0,part = body->contents.part; part; part = part->next)
  395.       display_body (&part->body,tmp,i++);
  396.   }
  397.   else {            /* non-multipart, output oneline descriptor */
  398.     if (!pfx) pfx = "";        /* dummy prefix if top level */
  399.     sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
  400.     if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
  401.     if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
  402.     if (par = body->parameter) do
  403.       sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
  404.     while (par = par->next);
  405.     if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
  406.     switch (body->type) {    /* bytes or lines depending upon body type */
  407.     case TYPEMESSAGE:        /* encapsulated message */
  408.     case TYPETEXT:        /* plain text */
  409.       sprintf (s += strlen (s)," (%ld lines)",body->size.lines);
  410.       break;
  411.     default:
  412.       sprintf (s += strlen (s)," (%ld bytes)",body->size.bytes);
  413.       break;
  414.     }
  415.     puts (tmp);            /* output this line */
  416.                 /* encapsulated message? */
  417.     if (body->type == TYPEMESSAGE && (body = body->contents.msg.body)) {
  418.       if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
  419.       else {            /* build encapsulation prefix */
  420.     sprintf (tmp,"%s%ld.",pfx,i);
  421.     display_body (body,tmp,(long) 0);
  422.       }
  423.     }
  424.   }
  425. }
  426.  
  427. /* MM status report
  428.  * Accepts: MAIL stream
  429.  */
  430.  
  431. void status (MAILSTREAM *stream)
  432. {
  433.   long i;
  434.   char date[50];
  435.   rfc822_date (date);
  436.   puts (date);
  437.   if (stream) {
  438.     if (stream->mailbox)
  439.       printf (" %s mailbox: %s, %ld messages, %ld recent\n",
  440.           stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
  441.     else puts ("%No mailbox is open on this stream");
  442.     if (stream->user_flags[0]) {
  443.       printf ("Keywords: %s",stream->user_flags[0]);
  444.       for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
  445.     printf (", %s",stream->user_flags[i]);
  446.       puts ("");
  447.     }
  448.   }
  449. }
  450.  
  451.  
  452. /* Prompt user for input
  453.  * Accepts: pointer to prompt message
  454.  *          pointer to input buffer
  455.  */
  456.  
  457. void prompt (char *msg,char *txt)
  458. {
  459.   printf ("%s",msg);
  460.   gets (txt);
  461. }
  462.  
  463. /* Interfaces to C-client */
  464.  
  465.  
  466. void mm_searched (MAILSTREAM *stream,long number)
  467. {
  468. }
  469.  
  470.  
  471. void mm_exists (MAILSTREAM *stream,long number)
  472. {
  473. }
  474.  
  475.  
  476. void mm_expunged (MAILSTREAM *stream,long number)
  477. {
  478. }
  479.  
  480.  
  481. void mm_flags (MAILSTREAM *stream,long number)
  482. {
  483. }
  484.  
  485.  
  486. void mm_notify (MAILSTREAM *stream,char *string,long errflg)
  487. {
  488.   mm_log (string,errflg);
  489. }
  490.  
  491.  
  492. void mm_mailbox (char *string)
  493. {
  494.   putchar (' ');
  495.   puts (string);
  496. }
  497.  
  498.  
  499. void mm_bboard (char *string)
  500. {
  501.   putchar (' ');
  502.   puts (string);
  503. }
  504.  
  505. void mm_log (char *string,long errflg)
  506. {
  507.   switch ((short) errflg) {
  508.   case NIL:
  509.     printf ("[%s]\n",string);
  510.     break;
  511.   case PARSE:
  512.   case WARN:
  513.     printf ("%%%s\n",string);
  514.     break;
  515.   case ERROR:
  516.     printf ("?%s\n",string);
  517.     break;
  518.   }
  519. }
  520.  
  521.  
  522. void mm_dlog (char *string)
  523. {
  524.   puts (string);
  525. }
  526.  
  527.  
  528. void mm_login (char *host,char *user,char *pwd,long trial)
  529. {
  530.   char tmp[MAILTMPLEN];
  531.   if (curhst) fs_give ((void **) &curhst);
  532.   curhst = (char *) fs_get (1+strlen (host));
  533.   strcpy (curhst,host);
  534.   if (*userbuf) {
  535.     curusr = cpystr (strcpy (user,userbuf));
  536.     printf ("{%s/user=%s} ",host,user);
  537.   }
  538.   else {
  539.     sprintf (tmp,"{%s} username: ",host);
  540.     prompt (tmp,user);
  541.   }
  542.   if (curusr) fs_give ((void **) &curusr);
  543.   curusr = cpystr (user);
  544.   prompt ("password: ",pwd);
  545. }
  546.  
  547.  
  548. void mm_critical (MAILSTREAM *stream)
  549. {
  550. }
  551.  
  552.  
  553. void mm_nocritical (MAILSTREAM *stream)
  554. {
  555. }
  556.  
  557.  
  558. long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
  559. {
  560. #if UNIXLIKE
  561.   kill (getpid (),SIGSTOP);
  562. #else
  563.   abort ();
  564. #endif
  565.   return NIL;
  566. }
  567.  
  568.  
  569. void mm_fatal (char *string)
  570. {
  571.   printf ("?%s\n",string);
  572. }
  573.  
  574. /* SMTP tester */
  575.  
  576. void smtptest (long debug)
  577. {
  578.   SMTPSTREAM *stream = NIL;
  579.   char line[MAILTMPLEN];
  580.   unsigned char *text = (unsigned char *) fs_get (8*MAILTMPLEN);
  581.   ENVELOPE *msg = mail_newenvelope ();
  582.   BODY *body = mail_newbody ();
  583.   msg->from = mail_newaddr ();
  584.   msg->from->personal = cpystr (personalname);
  585.   msg->from->mailbox = cpystr (curusr);
  586.   msg->from->host = cpystr (curhst);
  587.   msg->return_path = mail_newaddr ();
  588.   msg->return_path->mailbox = cpystr (curusr);
  589.   msg->return_path->host = cpystr (curhst);
  590.   prompt ("To: ",line);
  591.   rfc822_parse_adrlist (&msg->to,line,curhst);
  592.   if (msg->to) {
  593.     prompt ("cc: ",line);
  594.     rfc822_parse_adrlist (&msg->cc,line,curhst);
  595.   }
  596.   else {
  597.     prompt ("Newsgroups: ",line);
  598.     if (*line) msg->newsgroups = cpystr (line);
  599.     else {
  600.       mail_free_body (&body);
  601.       mail_free_envelope (&msg);
  602.       fs_give ((void **) &text);
  603.     }
  604.   }
  605.   prompt ("Subject: ",line);
  606.   msg->subject = cpystr (line);
  607.   puts (" Msg (end with a line with only a '.'):");
  608.   body->type = TYPETEXT;
  609.   *text = '\0';
  610.   while (gets (line)) {
  611.     if (line[0] == '.') {
  612.       if (line[1] == '\0') break;
  613.       else strcat ((char *) text,".");
  614.     }
  615.     strcat ((char *) text,line);
  616.     strcat ((char *) text,"\015\012");
  617.   }
  618.   body->contents.text = text;
  619.   rfc822_date (line);
  620.   msg->date = (char *) fs_get (1+strlen (line));
  621.   strcpy (msg->date,line);
  622.   if (msg->to) {
  623.     puts ("Sending...");
  624.     if (stream = smtp_open (hostlist,debug)) {
  625.       if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
  626.       else printf ("[Failed - %s]\n",stream->reply);
  627.     }
  628.   }
  629.   else {
  630.     puts ("Posting...");
  631.     if (stream = nntp_open (newslist,debug)) {
  632.       if (nntp_mail (stream,msg,body)) puts ("[Ok]");
  633.       else printf ("[Failed - %s]\n",stream->reply);
  634.     }
  635.   }
  636.   if (stream) smtp_close (stream);
  637.   else puts ("[Can't open connection to any server]");
  638.   mail_free_envelope (&msg);
  639.   mail_free_body (&body);
  640. }
  641.